﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Frogism.Domain;
using Frogism.Core;
namespace Frogism.Tests {
  [TestFixture]
  public class AccountTest {

    [SetUp]
    public void Init() {




    }
    public Account CreateAccount(int accountType) {
      Account a = new Account();
      a.AccountType = accountType;
      a.Name = "MyName";
      a.Id = 999;
      a.IsActive = false;
      a.MaxValue = 0;
      a.MinValue = 0;
      a.NextGoalValue = 1000;
      a.Purpose = "Golf";
      return a;
    }
    public Account CreateAccount() {
      return CreateAccount(DBConst.AccountTypeChecking);
    }
    protected decimal AddTransaction(Account a, decimal value, int TransactionTypeId, DateTime date, bool IsConfirmed) {
      a.Transactions.Add(new Transaction("Test" + value.ToString(), a.Id, TransactionType.Create(TransactionTypeId), value, date, IsConfirmed));
      return value;
    }
    protected decimal AddRandomTransaction(Account a, int TransactionTypeId, DateTime date, bool IsConfirmed) {
      Random r = new Random();
      decimal val = ((decimal)r.Next()) / 2;

      return AddTransaction(a, val, TransactionTypeId, date, IsConfirmed);
    }
    int Deposit = DBConst.TransactionTypeDeposit;
    int Expense = DBConst.TransactionTypeExpense;
    int Payment = DBConst.TransactionTypePayment;
    int Bill = DBConst.TransactionTypeBill;
    bool Confirmed = true;
    bool NotConfirmed = false;
    DateTime Now = DateTime.Now;
    DateTime LastMonth = DateTime.Now.AddMonths(-1);

    [Test] 
    public void YearStart(){
      Account a = CreateAccount();
      AddTransaction(a, 100m, DBConst.TransactionTypeDeposit, DateTime.Now.AddYears(-1),true);

      Assert.AreEqual(100, a.YearStart);
    }
    [Test]
    public void Balance() {
      Account a = CreateAccount();
      decimal DepositNow = AddRandomTransaction(a, Deposit, Now, Confirmed);
      decimal DepositLastMonth = AddRandomTransaction(a, Deposit, LastMonth, Confirmed);
      decimal ExpenseNotConfirmed = AddRandomTransaction(a, Expense, Now, NotConfirmed);
      decimal ExpenseConfirmed = AddRandomTransaction(a, Expense, Now, Confirmed);
      decimal ExpenseLastMonth = AddRandomTransaction(a, Expense, LastMonth, Confirmed);
      decimal ExpectedBalance = DepositNow + DepositLastMonth - ExpenseNotConfirmed - ExpenseConfirmed - ExpenseLastMonth;
      Assert.AreEqual(ExpectedBalance, a.Balance);
    }
    [Test]
    public void IsConfirmedOnBalance() {
      Account a = CreateAccount();
      decimal DepositLastMonth = AddRandomTransaction(a, Deposit, LastMonth, Confirmed);
      decimal ExpenseConfirmed = AddRandomTransaction(a, Expense, Now, Confirmed);
      decimal ExpenseLastMonth = AddRandomTransaction(a, Expense, LastMonth, Confirmed);

      Assert.AreEqual(a.ConfirmedBalance, DepositLastMonth - ExpenseConfirmed - ExpenseLastMonth);
    }
    [Test]
    public void ToGo() {
      Account a = CreateAccount();
      Assert.AreEqual(a.ToGo, a.NextGoalValue - a.Balance);
    }
    [Test]
    public void LastMonthBalance() {
      Account a = CreateAccount();
      decimal DepositLastMonth = AddRandomTransaction(a, Deposit, LastMonth, Confirmed);
      decimal BillLastMonth = AddRandomTransaction(a, Bill, LastMonth, Confirmed);
      decimal TransferLastMonth = AddRandomTransaction(a, DBConst.TransactionTypeTransfer, LastMonth, Confirmed);
      decimal DepositNow = AddRandomTransaction(a, Expense, Now, NotConfirmed);
      decimal ExpenseNowConfirmed = AddRandomTransaction(a, Expense, Now, Confirmed);
      decimal ExpenseLastMonth = AddRandomTransaction(a, Expense, LastMonth, Confirmed);
      decimal ExpenseLastMonthNotConfirmed = AddRandomTransaction(a, Expense, LastMonth, NotConfirmed);

      Assert.AreEqual(a.LastMonth, DepositLastMonth - BillLastMonth + TransferLastMonth - ExpenseLastMonth - ExpenseLastMonthNotConfirmed);
    }
    [Test]
    public void LastMonthBalanceExpenseLastMonthNotConfirmed() {
      Account a = CreateAccount();
      decimal ExpenseLastMonthNotConfirmed = AddRandomTransaction(a, Expense, LastMonth, NotConfirmed);
      Assert.AreEqual(-1*ExpenseLastMonthNotConfirmed, a.LastMonth);
    }
    [Test]
    public void LastMonthBalanceExpenseLastMonth() {
      Account a = CreateAccount();
      decimal ExpenseLastMonth = AddRandomTransaction(a, Expense, LastMonth, Confirmed);
      Assert.AreEqual(-1 * ExpenseLastMonth, a.LastMonth);
    }
    [Test]
    public void LastMonthBalanceExpenseNowConfirmed() {
      Account a = CreateAccount();
      decimal ExpenseNowConfirmed = AddRandomTransaction(a, Expense, Now, Confirmed);
      Assert.AreEqual(a.LastMonth, 0);
    }
    [Test]
    public void LastMonthBalanceDepositNow() {
      Account a = CreateAccount();
      decimal DepositNow = AddRandomTransaction(a, Expense, Now, NotConfirmed);
      Assert.AreEqual(a.LastMonth, 0);
    }
    [Test]
    public void LastMonthBalanceTransferLastMonth() {
      Account a = CreateAccount();
      decimal TransferLastMonth = AddRandomTransaction(a, DBConst.TransactionTypeTransfer, LastMonth, Confirmed);
      Assert.AreEqual(a.LastMonth, TransferLastMonth);
    }
    [Test]
    public void LastMonthBalanceBillLastMonth() {
      Account a = CreateAccount();
      decimal BillLastMonth = AddRandomTransaction(a, Bill, LastMonth, Confirmed);
      Assert.AreEqual(-1*BillLastMonth,a.LastMonth);
    }
    [Test]
    public void LastMonthBalanceDepositLastMonth() {
      Account a = CreateAccount(DBConst.AccountTypeChecking);
      decimal DepositLastMonth = AddRandomTransaction(a, Deposit, LastMonth, Confirmed);
      Assert.AreEqual(a.LastMonth, DepositLastMonth);
    }
    [Test]
    public void RemainingDebitDepositNow() {
      Account a = CreateAccount(DBConst.AccountTypeCreditCard);
      a.MinValue = -1000;
      decimal ExpenseNow = AddTransaction(a, 100, Expense, Now, Confirmed);
    
      Assert.AreEqual(-1*(a.MinValue) - ExpenseNow,a.Remaining);
    }
    [Test]
    public void RemainingCheckingDepositNow() {
      Account a = CreateAccount(DBConst.AccountTypeChecking);
      decimal DepositNow = AddRandomTransaction(a, Deposit, Now, Confirmed);
      Assert.AreEqual(DepositNow, a.Remaining, "Credit");

    }
    [Test]
    public void RemainingCheckingDepositLastMonth() {
      Account a = CreateAccount(DBConst.AccountTypeChecking);
      decimal DepositLastMonth = AddRandomTransaction(a, Deposit, LastMonth, Confirmed);
      Assert.AreEqual(DepositLastMonth, a.Remaining, "Credit");
    }
    [Test]
    public void RemainingCheckingExpenseNotConfirmed() {
      Account a = CreateAccount(DBConst.AccountTypeChecking);
      decimal ExpenseNotConfirmed = AddRandomTransaction(a, Expense, Now, NotConfirmed);
      Assert.AreEqual(-1 * ExpenseNotConfirmed, a.Remaining, "Credit");

    }
    [Test]
    public void RemainingCheckingExpenseConfirmed() {
      Account a = CreateAccount(DBConst.AccountTypeChecking);
      decimal ExpenseConfirmed = AddRandomTransaction(a, Expense, Now, Confirmed);
      Assert.AreEqual(-1 * ExpenseConfirmed, a.Remaining, "Credit");
    }
    [Test]
    public void RemainingCheckingExpenseLastMonth() {
      Account a = CreateAccount(DBConst.AccountTypeChecking);
      decimal ExpenseLastMonth = AddRandomTransaction(a, Expense, LastMonth, Confirmed);
      Assert.AreEqual(-1 * ExpenseLastMonth, a.Remaining, "Credit");
    }
    [Test]
    public void RemainingCreditCard() {
      Account a = CreateAccount(DBConst.AccountTypeCreditCard);
      a.MinValue = -3000;
      decimal PaymentNow = AddTransaction(a, 50, Payment, Now, Confirmed);
      decimal PaymentLastMonth = AddTransaction(a, 50, Payment, LastMonth, Confirmed);
      decimal ExpenseNotConfirmed = AddTransaction(a, 33, Expense, Now, NotConfirmed);
      decimal ExpenseConfirmed = AddTransaction(a, 44, Expense, Now, Confirmed);
      decimal ExpenseLastMonth = AddTransaction(a,55, Expense, LastMonth, Confirmed);

      decimal ExpectedBalance = ExpenseNotConfirmed + ExpenseConfirmed + ExpenseLastMonth - PaymentNow - PaymentLastMonth;
      Assert.AreEqual(3000+50+50-33-44-55, a.Remaining, "Debit");

    }
    [Test]
  [ExpectedException(ExceptionType=typeof(System.NotImplementedException))]
    public void InvalidTransationType() {
      Account a = CreateAccount(DBConst.AccountTypeCreditCard);
      decimal DepositNow = AddRandomTransaction(a, -1, Now, Confirmed);
      // decimal DepositLastMonth = AddRandomTransaction(a, Deposit, LastMonth, Confirmed);

      Assert.AreEqual(0, a.Remaining, "Debit");
    }
    [Test]
    public void AddTransaction() {
      Account a = CreateAccount();
      decimal bBalance = a.Balance;
      decimal bLastMonth = a.LastMonth;
      decimal bRemaing = a.Remaining;
      a.AccountType = DBConst.AccountTypeChecking;
      Transaction t = new Transaction("AddedTransaction", a.Id, DBConst.TransactionTypeDeposit, 999.88m, DateTime.Now, true);
      a.Transactions.Add(t);
      Assert.AreEqual(bBalance + 999.88m, a.Balance, "Balance");
      Assert.AreEqual(bLastMonth, a.LastMonth, "LastMonth");
      Assert.AreEqual(bRemaing + 999.88m, a.Remaining, "Remaining");
    }
    [Test]
    public void Change() {
      Account a = CreateAccount();
      Assert.AreEqual(a.Balance - a.LastMonth, a.Change);
    }
  }
}
